#pragma once

#include "Containers/String.h"


enum class EClassFlags
{
    //specify extra header files in .m.cpp
    //usage: RCLASS(ExtraHeader=["Material/Material.h"] )
    C_ExtraHeader,

    //specify export macro files in .m.h
    //usage: RENUM(ExportMacro="WHENGINE_API")
    C_ExportMacro, 

	//specify interface class names
	//usage: RCLASS(Interfaces=["InterfaceName1","InterfaceName2"])
	C_Interfaces,
};

//start with P_
enum class EPropertyFlags
{
	P_None,

	// No value falg, property with this flag will be saved 
	P_Saveable, 

	//string type flag , set name of property 
	P_Name, 

	// No value falg,display inner property in editor, used for property like vector3, vector4, or smart pointer
	P_DisplayInner,

	// No value falg, don't expose property to script
	P_NotInScript,

	// do not serialize this property
	P_NoSerialize,

	//force serialize this property as binary
	//only support for TVector<T> type, the T must not contain any pointer/Smart pointer 
	P_SerializeAsBinary,
};

enum class EFunctionFlags
{
	F_None,

	// No value falg, don't expose function to script
	F_NotInScript,

	// No value falg, will create a script constructor for this class
	F_ScriptConstructor,
};

struct SReflectionMetaDataValue
{

public:
	SReflectionMetaDataValue() = default;
	~SReflectionMetaDataValue() = default;

	SReflectionMetaDataValue(bool InBoolValue)
		: BoolValue(InBoolValue)
		, ValueType(EValueType::Bool)
	{
	}

	SReflectionMetaDataValue(double InDoubleValue)
		: DoubleValue(InDoubleValue)
		, ValueType(EValueType::Double)
	{
	}

	SReflectionMetaDataValue(const CString& InStringValue)
		: StringValue(InStringValue)
		, ValueType(EValueType::String)
	{
	}

	SReflectionMetaDataValue(const TVector<CString>& InStringArrayValue)
		: StringArrayValue(InStringArrayValue)
		, ValueType(EValueType::StringArray)
	{
	}

protected:

	bool BoolValue;
	double DoubleValue;
	CString StringValue;
	TVector<CString> StringArrayValue;
	
	enum class EValueType
	{
		None,
		Bool,
		Double,
		String,
		StringArray,
	};

	EValueType ValueType = EValueType::None;

};





#define COMBINE_4_STRING_IMPL(A,B,C,D) A##B##C##D
#define COMBINE_4_STRING(A,B,C,D) COMBINE_4_STRING_IMPL(A,B,C,D)

//FILE_ID is defined in .m.h
//FILE_ID and line number are used to generate unique source code position
//cant directly combine with ##, because FILE_ID is a macro
#define ROBJECT COMBINE_4_STRING(FILE_ID,_,__LINE__,_Object)
#define RCLASS(...) COMBINE_4_STRING(FILE_ID,_,__LINE__,_Class)
#define RSTRUCT(...) //it is empty now
#define RENUM(...) //it is empty now
#define RINTERFACE(...) //it is empty now

#define RFIELD(...)
#define RPROPERTY(...)
#define RFUNCTION(...)

